/*
 * BasicTypes.h
 *
 *  Created on: 10.08.2011
 *      Author: Blinov Kirill
 *   Copyright: LGPL
 *
 */
#ifndef BASICTYPES_H_
#define BASICTYPES_H_

#include <stdint.h>
#include <stddef.h>
#include <stdio.h>

#ifdef WIN32

#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/wglew.h>
#include <GL/glext.h>

#elif defined(linux) || defined(__linux)
#define GL3_PROTOTYPES 1
#include <GL3/gl3.h>
#include <GL/glu.h>
#elif defined(__APPLE__)
#	include <OpenGL/gl.h>
#else
#	error "Unsupported platform"
#endif

#include <string>

#include <gli/gli.hpp>
#include <gli/gtx/gl_texture2d.hpp>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/half_float.hpp>
#include <glm/gtc/type_precision.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/rotate_vector.hpp>
#include <glm/gtx/quaternion.hpp>

// TODO define correct types
//typedef int   __int32
//typedef short	__int16

#define BYTE   unsigned char
#define SHORT  short int
#define USHORT unsigned short int
#define UINT   unsigned int
#define UINT64 unsigned long long

//#define ENGINE_DEBUG

/*
 * Common information types could be sent to a shader program
 */
enum SHADER_INPUT_COMMON_VALUES
{
	SHADER_INPUT_MVP_MATRIX = 0,
	SHADER_INPUT_MODEL_MATRIX,
	SHADER_INPUT_BONES_ARRAY_32,
	SHADER_INPUT_LIGHT_DIRECTION,
	SHADER_INPUT_AMBLIENT_COLOR,
	SHADER_INPUT_CAMERA_DISTANCE,
	SHADER_INPUT_DIFFUSE_MAP
};

/*
 * Unit types
 */
enum UNIT_TYPES
{
	UNIT_TYPE_HEAVY_JET = 0,
	UNIT_TYPE_MEDIUM_JET ,
	UNIT_TYPE_LIGHT_JET,
	UNIT_TYPE_RACKET_,
	UNIT_TYPE_MILK,
	UNIT_TYPE_BULLET,
	UNIT_TYPE_BONUS,
	UNIT_TYPE_SCENARY,
	UNIT_TYPES_TOTAL_COUNT
};

struct SCREEN_DIMENSION
{
	SCREEN_DIMENSION(){};
	SCREEN_DIMENSION( UINT Height, UINT Width ):
		height(Height), width(Width), sdlFlags(0), multisampleBufferCount(0)
	{
	};
	SCREEN_DIMENSION( const SCREEN_DIMENSION& Dimension ) :
		height(Dimension.height), width(Dimension.width), sdlFlags(Dimension.sdlFlags),
		multisampleBufferCount(Dimension.multisampleBufferCount)
	{
	};
	UINT  height;
	UINT  width;
	UINT  sdlFlags;
	USHORT multisampleBufferCount;
};

/*
 * One vertex structure
 */
struct STANDART_VERTEX
{
	STANDART_VERTEX():
		position(0.0f,0.0f,0.0f),normal(0.0f,0.0f,0.0f),texture(0.0f,0.0f), bonesWeights(1.0f,0.0f,0.0f), bonesIndexesAndTextureNumber(1.0f,0.0f,0.0f,0.0f) {};
	STANDART_VERTEX( glm::vec3 Position, glm::vec3 Normal, glm::vec2 Texture, glm::vec3 Weights, glm::vec3 Indexes, float TextureNumber ) :
		position(Position), normal(Normal), texture(Texture), bonesWeights(Weights), bonesIndexesAndTextureNumber(Indexes, TextureNumber) {};
	glm::vec3 position;
	glm::vec3 normal;
	glm::vec2 texture;
	glm::vec3 bonesWeights;
	glm::vec4 bonesIndexesAndTextureNumber;
};

struct TEXTURE_DESCRIPTOR
{
	TEXTURE_DESCRIPTOR():
		number(0), textureGLid (0), textureType(0)
		{}
	TEXTURE_DESCRIPTOR( const std::string Name, const short Number ) :
		name(Name), alias(Name), number(Number), textureGLid (0), textureType(0)
	    {}
	TEXTURE_DESCRIPTOR( const std::string Name, const short Number, const GLuint TextureName,
			            const GLenum Type ) :
		name(Name), alias(Name), number(Number), textureGLid (TextureName), textureType(Type)
	    {}
	//The name used for descriptor identification
	std::string alias;
	//Texture file name
	std::string name;
	//Texture number in model
	short       number;
	//OpenGL texture or texture array this texture belongs to id
	GLuint      textureGLid;
    //Type of texture, can be GL_TEXTURE_2D, GL_TEXTURE_2D_ARRAY, e.t.c
	GLenum      textureType;
};

struct SHADER_COMMON_PARAMS
{
	glm::mat4            ModelMatrix;
	glm::mat4            ViewMatrix;
	glm::mat4            ProjectionMatrix;
	glm::vec3            LightDirection;
	glm::vec3            AmblientColor;
	float                CameraDistance;
	TEXTURE_DESCRIPTOR   DiffuseTexture;
};

/* A class to play animation for subobject  */
class IAnimationController
{
	IAnimationController(){};
	~IAnimationController(){};
};

struct GUI_ELEMENT
{
	glm::vec2 position;
	glm::vec2 size;
	GLuint texture;
	std::string text;
	glm::vec2 positionText;
	glm::vec2 sizeText;
};

/*
 * Camera render options
 */
struct VISUAL_PARAMS
{

};

/*
 * Camera description
 */
const USHORT PARALLELEPIPED_PLANE_COUNT = 6;
struct GAME_CAMERA
{
	GAME_CAMERA() : lightDirection( 1.0f, 0.0f, -1.0f ), amblientColor( 0.0f, 0.0f, 0.0f )
	{ };
	float         			leftTopX;
	float         			leftTopY;
	float         			height;
	float         			width;
	VISUAL_PARAMS 			visualParams;
	glm::vec3     			lightDirection;
	glm::vec3     			amblientColor;
	glm::vec4     			sphere; //Culling sphere
	glm::vec4               frustum[PARALLELEPIPED_PLANE_COUNT]; //Culling frustum
	glm::mat4     			viewMatrix;
	glm::mat4     			projectionMatrix;
};

/*
 *
 *
 *
 */
const USHORT MOUSE_BUTTON_LEFT = 0;
const USHORT MOUSE_BUTTON_MIDDLE = 1;
const USHORT MOUSE_BUTTON_RIGHT = 2;

const USHORT MOUSE_KEY_COUNT = 3;
const USHORT MOUSE_KEY_DOWN = 0;
const USHORT MOUSE_KEY_UP = 1;

struct INPUT_MESSAGE
{
	INPUT_MESSAGE(): terminateApplication(false), mouseDelta( 0.0f, 0.0f ), mousePosition ( 0.0f, 0.0f )
			    {
					memset( mouseKeys, 0, sizeof(mouseKeys) );
					keys.reserve( 5 ); //reserve space for 5 keys
			    }

	//Should the application be terminated
	bool terminateApplication;

	//Delta of mouse position
	glm::vec2 mouseDelta;

	//TODO Delete when start using animated cusor.
	glm::vec2 mousePosition;

	//Mouse keys
    USHORT mouseKeys[MOUSE_KEY_COUNT];

	//Hight bit is a state bit ( 1 - Down, 0 - Up ), other bits are ASCII character or a special key code
	std::vector<USHORT> keys;
};

/*Unit event*/
struct UINT_EVENT
{
	UINT type;
};

/* Temporary structure for unit physic parameters */
struct UNIT_PHYSIC_PARAMS
{
	UNIT_PHYSIC_PARAMS() : initialPosition( 0.0, 0.0, 0.0 ), initialOrientation( 1.0, glm::vec3( 0.0f, 0.0f, 0.0f ) )
	{}
	glm::vec3                    initialPosition;
	glm::quat                    initialOrientation;
};

#endif /* BASICTYPES_H_ */
